/*
 *Copyright (c) 2024 Black Sesame Technologies
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
*/
/**
 * @file  ipc_trans_runtime.h
 * @brief this file is used as the api to access ipc tranferring layer.
 * this api may be used by ipc_app_layer directly, or related driver developers
 * may implement ipc_trans_impl.c to adapt to different OSs.
 * @note
 * @details feature list
 */
#ifndef _IPC_TRANS_RUNTIME_H
#define _IPC_TRANS_RUNTIME_H

#include "ipc_hw_common.h"
#include "ipc_hw_layer.h"
#include "ipc_hw_impl.h"

#include "ipc_trans_config.h"
#include "ipc_trans_common.h"

#include "bst_ipc_config.h"
#include "ipc_trans_ses_mgt.h"
#include "ipc_trans_cfg.h"
#include "ipc_trans_sts_mgt.h"

#ifdef __cplusplus
extern "C" {
#endif

struct _debug_info_t {
	uint8_t role;
#ifdef DEBUG_MODE_ENABLE
	_Atomic uint8_t send_fail_cnt;
	uint8_t send_frame_cnt;
	uint8_t reserved;

	_Atomic uint32_t send_msg_cnt;
	_Atomic uint32_t send_rw_msg_cnt;

	_Atomic uint32_t recv_rw_msg_cnt;
	_Atomic uint32_t recv_msg_1_cnt;
	_Atomic uint32_t recv_msg_2_cnt;
#endif
#ifdef TIMESTAMP_DEBUG_ENABLE
	uint64_t send_start_time;
	uint64_t send_end_time;
	uint64_t collate_time;
	uint64_t get_msg_time;
#endif
};
#define debug_info_t struct _debug_info_t

struct _msgbx_end_device_t {
	// basic hw ops and info
	libipc_hw_compat_ops_t ops;
#if !defined(BAREMETAL_VERSION_TRUNCATE)
	msgbx_hw_info_t hw_info;
	int16_t method_register_map[CMD_MAX_COUNT];
#endif
#if !defined(USE_EXTERNAL_MSG_BUFFER)
	ipc_ses_t ses_map[CHANNEL_COUNT][SESSION_COUNT];
#else
	ipc_ses_t **ses_map;
#endif
	ipc_flt_cfg_t cfg_map[CHANNEL_COUNT - 1];
	uint8_t g_ipc_pid;
	uint8_t g_ipc_flt_cnt;
#ifndef REMOVE_STS_MGT
	int16_t g_update_ses_list[CHANNEL_COUNT * SESSION_COUNT];
	uint8_t g_req_endmap_cid;
	_Atomic uint64_t g_end_sts_map;
#endif
#ifdef ENABLE_REMOTE_LOG_PROCESS_FUNC
	uint8_t g_log_tok;
#endif
#ifdef DEBUG_MODE_ENABLE
	debug_info_t debug_info[CHANNEL_COUNT][SESSION_COUNT];
#endif
};
#define msgbx_end_device_t struct _msgbx_end_device_t

#define TRANS_LAYER_VERSION 2
#define IPC_HW_LAYER_VERSION 1

/********************* extern global function *******************/
extern int32_t ipc_trans_complete(const uint8_t cpuid, const uint8_t ses_id);
extern int32_t ipc_trans_complete_sts(const uint8_t cpuid);

static inline int8_t session_dist(uint8_t info, uint8_t *sid, uint8_t *fid)
{
	*sid = info >> 4;
	*fid = info & 0x0f;
	return 0;
}

int32_t ipc_trans_layer_start(const uint8_t endid, uint8_t role);
int32_t ipc_trans_layer_stop(const uint8_t endid);

int32_t ipc_trans_init(const uint8_t role, err_msg_callback err_func,
		       void *dev_info);
int32_t ipc_trans_deinit(void *dev_info);

int32_t ipc_trans_create_session(const uint8_t sid, const uint8_t fid,
				 const uint8_t cid, const uint8_t role,
				 uint8_t *ses_id, void *dev_info);
int32_t ipc_trans_close_session(const uint8_t ses_id, void *dev_info);

int32_t ipc_trans_read_msg(const uint8_t fid, const uint8_t mode,
			   void *dev_info);

int32_t ipc_trans_send_msg(const uint8_t ses_id, serdes_t *msg,
			   const uint8_t type, void *dev_info);
int32_t ipc_trans_get_msg(const uint8_t ses_id, const ipc_msg_type_t msg_typ,
			  serdes_t *msg, void *dev_info);

int32_t ipc_trans_register_method(const uint8_t session_id, const uint8_t cmd,
				  void *dev_info);
int32_t ipc_trans_unregister_method(const uint8_t session_id, void *dev_info);

int32_t ipc_trans_get_avail_info(const uint8_t session_id, uint8_t *type,
				 void *dev_info);

int32_t ipc_trans_err_hdl(const uint8_t type, const uint8_t id,
			  const uint32_t hdl, void *dev_info);

int32_t ipc_trans_get_debug_info(const uint8_t ses_id, debug_info_t *info,
				 void *dev_info);
int32_t ipc_trans_end_sts_broadcast(void *addr);

int32_t ipc_trans_transmit_log(const uint8_t cid, const char *log,
			       void *dev_info);
int32_t ipc_trans_query_remote_endmap(void *dev_info);

int32_t ipc_trans_send_rwmsg(const uint8_t ses_id, rw_msg_t *msg,
			     void *dev_info);
int32_t ipc_trans_get_rwmsg(const uint8_t ses_id, rw_msg_t *msg,
			    uint64_t *timestamp, void *dev_info);
int8_t session_isvalid(const uint8_t session_id, void *addr);
#ifdef __cplusplus
}
#endif
#endif
